`timescale 1ns/1ps

module tb_fake_systolic_muxed_axi;
    reg clk;
    reg reset;
    reg start;
    reg [1:0] matrix_type;
    wire [31:0] c_out_muxed;
    wire        c_out_valid;
    wire        fake_done;
    wire        axi_done;
    wire        data_ready;

    // AXI signals
    wire [31:0] M_AXI_AWADDR;
    wire        M_AXI_AWVALID;
    reg         M_AXI_AWREADY;
    wire [31:0] M_AXI_WDATA;
    wire [3:0]  M_AXI_WSTRB;
    wire        M_AXI_WVALID;
    reg         M_AXI_WREADY;
    reg  [1:0]  M_AXI_BRESP;
    reg         M_AXI_BVALID;
    wire        M_AXI_BREADY;

    // 生成时钟
    initial clk = 0;
    always #5 clk = ~clk;

    // DUT: fake_systolic_muxed
    fake_systolic_muxed u_fake (
        .clk(clk),
        .reset(reset),
        .start(start),
        .matrix_type(matrix_type),
        .c_out_muxed(c_out_muxed),
        .c_out_valid(c_out_valid),
        .done(fake_done)
    );

    // DUT: c_out_axi_master
    axi_master_writer u_axi (
        .clk(clk),
        .reset(reset),
        .start(start),
        .data_in(c_out_muxed),
        .data_valid(c_out_valid),
        .data_done(fake_done),
        .data_ready(data_ready),
        .M_AXI_AWADDR(M_AXI_AWADDR),
        .M_AXI_AWVALID(M_AXI_AWVALID),
        .M_AXI_AWREADY(M_AXI_AWREADY),
        .M_AXI_WDATA(M_AXI_WDATA),
        .M_AXI_WSTRB(M_AXI_WSTRB),
        .M_AXI_WVALID(M_AXI_WVALID),
        .M_AXI_WREADY(M_AXI_WREADY),
        .M_AXI_BRESP(M_AXI_BRESP),
        .M_AXI_BVALID(M_AXI_BVALID),
        .M_AXI_BREADY(M_AXI_BREADY),
        .axi_done(axi_done)
    );

    // AXI slave仿真逻辑
    reg [7:0] axi_write_cnt;
    initial begin
        M_AXI_AWREADY = 0;
        M_AXI_WREADY  = 0;
        M_AXI_BVALID  = 0;
        M_AXI_BRESP   = 2'b00;
        axi_write_cnt = 0;
    end

    always @(posedge clk) begin
        // AW通道
        if (M_AXI_AWVALID && !M_AXI_AWREADY) begin
            M_AXI_AWREADY <= 1;
        end else begin
            M_AXI_AWREADY <= 0;
        end
        // W通道
        if (M_AXI_WVALID && !M_AXI_WREADY) begin
            M_AXI_WREADY <= 1;
            $display("[AXI] Write #%0d: ADDR=0x%08x DATA=0x%08x", axi_write_cnt, M_AXI_AWADDR, M_AXI_WDATA);
            axi_write_cnt <= axi_write_cnt + 1;
        end else begin
            M_AXI_WREADY <= 0;
        end
        // B通道
        if (M_AXI_WVALID && M_AXI_WREADY) begin
            M_AXI_BVALID <= 1;
        end else if (M_AXI_BREADY && M_AXI_BVALID) begin
            M_AXI_BVALID <= 0;
        end
    end

    // 新增：显示每一条分时复用输出
    reg [7:0] muxed_cnt;
    always @(posedge clk) begin
        if (reset || start) begin
            muxed_cnt <= 0;
        end else if (c_out_valid) begin
            $display("[MUXED] matrix_type=%0d, cnt=%0d, c_out_muxed=0x%08x", matrix_type, muxed_cnt, c_out_muxed);
            muxed_cnt <= muxed_cnt + 1;
        end
    end

    // 主控流程
    initial begin
        reset = 1;
        start = 0;
        matrix_type = 0;
        #30;
        reset = 0;
        #20;
        // 依次验证三种分时复用
        repeat(3) begin : TEST_ALL_TYPE
            @(negedge clk);
            start = 1;
            @(negedge clk);
            start = 0;
            wait(axi_done);
            $display("\n==== matrix_type = %0d AXI写入完成 ====\n", matrix_type);
            #20;
            matrix_type = matrix_type + 1;
            axi_write_cnt = 0;
            #40;
        end
        $display("\nAll test finished!\n");
        $stop;
    end
endmodule 